"""
认证和权限管理相关的Pydantic模式
"""

from pydantic import BaseModel, EmailStr, Field, field_validator, model_validator
from typing import Optional, List, Dict, Any
from datetime import datetime
from enum import Enum

from app.utils.timezone_utils import get_shanghai_now


class UserStatus(str, Enum):
    """用户状态枚举"""
    ACTIVE = "active"
    INACTIVE = "inactive"
    LOCKED = "locked"





# ============ 基础模式 ============

class PermissionBase(BaseModel):
    """权限基础模式"""
    name: str = Field(..., description="权限名称")
    display_name: str = Field(..., description="权限显示名称")
    description: Optional[str] = Field(None, description="权限描述")
    resource: str = Field(..., description="资源类型")
    action: str = Field(..., description="操作类型")


class PermissionCreate(PermissionBase):
    """创建权限模式"""
    pass


class PermissionUpdate(BaseModel):
    """更新权限模式"""
    display_name: Optional[str] = None
    description: Optional[str] = None


class PermissionResponse(PermissionBase):
    """权限响应模式"""
    id: int
    is_system: bool
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True

    @field_validator('is_system', mode='before')
    @classmethod
    def validate_is_system(cls, v):
        """处理 is_system 字段的 None 值"""
        if v is None:
            return False
        return bool(v)


class RoleBase(BaseModel):
    """角色基础模式"""
    name: str = Field(..., min_length=2, max_length=50, description="角色名称")
    display_name: str = Field(..., min_length=2, max_length=100, description="角色显示名称")
    description: Optional[str] = Field(None, description="角色描述")


class RoleCreate(RoleBase):
    """创建角色模式"""
    permission_ids: Optional[List[int]] = Field(default=[], description="权限ID列表")


class RoleUpdate(BaseModel):
    """更新角色模式"""
    display_name: Optional[str] = None
    description: Optional[str] = None
    is_active: Optional[bool] = None
    permission_ids: Optional[List[int]] = None


class RoleResponse(RoleBase):
    """角色响应模式"""
    id: int
    is_system: bool
    is_active: bool
    created_at: datetime
    updated_at: datetime
    permissions: List[PermissionResponse] = []

    class Config:
        from_attributes = True


class UserBase(BaseModel):
    """用户基础模式"""
    username: str = Field(..., min_length=3, max_length=50, description="用户名")
    email: EmailStr = Field(..., description="邮箱地址")
    full_name: Optional[str] = Field(None, max_length=100, description="真实姓名")
    phone: Optional[str] = Field(None, max_length=20, description="手机号码")
    department: Optional[str] = Field(None, max_length=100, description="部门")
    position: Optional[str] = Field(None, max_length=100, description="职位")

    @field_validator('username')
    @classmethod
    def validate_username(cls, v):
        if not v.replace('_', '').replace('-', '').isalnum():
            raise ValueError('用户名只能包含字母、数字、下划线和连字符')
        return v


class UserCreate(UserBase):
    """创建用户模式"""
    password: str = Field(..., min_length=8, max_length=128, description="密码")
    role_ids: Optional[List[int]] = Field(default=[], description="角色ID列表")

    @field_validator('password')
    @classmethod
    def validate_password(cls, v):
        if not any(c.isupper() for c in v):
            raise ValueError('密码必须包含至少一个大写字母')
        if not any(c.islower() for c in v):
            raise ValueError('密码必须包含至少一个小写字母')
        if not any(c.isdigit() for c in v):
            raise ValueError('密码必须包含至少一个数字')
        if not any(c in '!@#$%^&*()_+-=[]{}|;:,.<>?' for c in v):
            raise ValueError('密码必须包含至少一个特殊字符')
        return v


class UserUpdate(BaseModel):
    """更新用户模式"""
    email: Optional[EmailStr] = None
    full_name: Optional[str] = None
    phone: Optional[str] = None
    department: Optional[str] = None
    position: Optional[str] = None
    is_active: Optional[bool] = None
    role_ids: Optional[List[int]] = None


class UserResponse(UserBase):
    """用户响应模式"""
    id: int
    avatar_url: Optional[str] = None
    is_active: bool
    is_superuser: bool
    last_login: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime
    roles: List[RoleResponse] = []

    class Config:
        from_attributes = True

    @model_validator(mode='before')
    @classmethod
    def extract_roles(cls, values):
        """从User对象中提取角色信息，避免在序列化时触发懒加载"""
        if hasattr(values, 'user_roles'):
            # 如果是User对象，手动提取角色信息
            roles = []
            for ur in values.user_roles:
                # 更宽松的布尔值检查，处理MySQL tinyint(1)的情况
                ur_active = ur.is_active in (True, 1, '1')
                role_active = ur.role and (ur.role.is_active in (True, 1, '1', None))

                if ur_active and ur.role and role_active:
                    role_data = {
                        'id': ur.role.id,
                        'name': ur.role.name,
                        'display_name': ur.role.display_name,
                        'description': ur.role.description,
                        'is_system': bool(ur.role.is_system),
                        'is_active': bool(ur.role.is_active),
                        'created_at': ur.role.created_at,
                        'updated_at': ur.role.updated_at,
                        'permissions': []
                    }

                    # 提取权限信息
                    if hasattr(ur.role, 'role_permissions'):
                        for rp in ur.role.role_permissions:
                            rp_active = rp.is_active in (True, 1, '1')
                            if rp_active and rp.permission:
                                permission_data = {
                                    'id': rp.permission.id,
                                    'name': rp.permission.name,
                                    'display_name': rp.permission.display_name,
                                    'description': rp.permission.description,
                                    'resource': rp.permission.resource,
                                    'action': rp.permission.action,
                                    'is_system': bool(rp.permission.is_system),
                                    'created_at': rp.permission.created_at,
                                    'updated_at': rp.permission.updated_at
                                }
                                role_data['permissions'].append(permission_data)

                    roles.append(role_data)

            # 创建一个新的字典，包含所有User属性和提取的roles
            result = {}
            for field in ['id', 'username', 'email', 'full_name', 'phone', 'department',
                         'position', 'avatar_url', 'last_login', 'created_at', 'updated_at']:
                if hasattr(values, field):
                    result[field] = getattr(values, field)

            # 特殊处理布尔字段，确保正确转换MySQL的tinyint(1)
            if hasattr(values, 'is_active'):
                result['is_active'] = bool(getattr(values, 'is_active'))

            if hasattr(values, 'is_superuser'):
                result['is_superuser'] = bool(getattr(values, 'is_superuser'))

            result['roles'] = roles
            return result

        return values


class UserProfile(BaseModel):
    """用户个人资料模式 - 包含完整的用户信息"""
    id: int
    username: str
    email: str
    full_name: Optional[str] = None
    avatar_url: Optional[str] = None
    phone: Optional[str] = None
    department: Optional[str] = None
    position: Optional[str] = None
    is_active: bool
    is_superuser: bool
    last_login: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime
    roles: List[RoleResponse] = []
    permissions: List[PermissionResponse] = []

    class Config:
        from_attributes = True

    @model_validator(mode='before')
    @classmethod
    def extract_user_info(cls, values):
        """从User对象中提取完整的用户信息"""
        if hasattr(values, 'user_roles'):
            # 如果是User对象，手动提取信息
            roles = []
            all_permissions = set()

            for ur in values.user_roles:
                # 更宽松的布尔值检查
                ur_active = ur.is_active in (True, 1, '1')
                role_active = ur.role and (ur.role.is_active in (True, 1, '1', None))

                if ur_active and ur.role and role_active:
                    role_data = {
                        'id': ur.role.id,
                        'name': ur.role.name,
                        'display_name': ur.role.display_name,
                        'description': ur.role.description,
                        'is_system': bool(ur.role.is_system),
                        'is_active': bool(ur.role.is_active),
                        'created_at': ur.role.created_at or get_shanghai_now(),
                        'updated_at': ur.role.updated_at or get_shanghai_now(),
                        'permissions': []
                    }

                    # 提取权限信息
                    if hasattr(ur.role, 'role_permissions'):
                        for rp in ur.role.role_permissions:
                            rp_active = rp.is_active in (True, 1, '1')
                            if rp_active and rp.permission:
                                permission_data = {
                                    'id': rp.permission.id,
                                    'name': rp.permission.name,
                                    'display_name': rp.permission.display_name,
                                    'description': rp.permission.description,
                                    'resource': rp.permission.resource,
                                    'action': rp.permission.action,
                                    'is_system': bool(rp.permission.is_system),
                                    'created_at': rp.permission.created_at or get_shanghai_now(),
                                    'updated_at': rp.permission.updated_at or get_shanghai_now()
                                }
                                role_data['permissions'].append(permission_data)
                                all_permissions.add(rp.permission.name)

                    roles.append(role_data)

            # 创建一个新的字典，包含所有User属性
            result = {}
            for field in ['id', 'username', 'email', 'full_name', 'phone', 'department',
                         'position', 'avatar_url', 'last_login', 'created_at', 'updated_at']:
                if hasattr(values, field):
                    result[field] = getattr(values, field)

            # 特殊处理布尔字段
            if hasattr(values, 'is_active'):
                result['is_active'] = bool(getattr(values, 'is_active'))

            if hasattr(values, 'is_superuser'):
                result['is_superuser'] = bool(getattr(values, 'is_superuser'))

            result['roles'] = roles

            # 将权限转换为PermissionResponse对象
            permissions = []
            for role in roles:
                permissions.extend(role['permissions'])
            result['permissions'] = permissions

            return result

        return values


# ============ 认证相关模式 ============

class LoginRequest(BaseModel):
    """登录请求模式"""
    username: str = Field(..., description="用户名或邮箱")
    password: str = Field(..., description="密码")
    remember_me: bool = Field(default=False, description="记住我")


class LoginResponse(BaseModel):
    """登录响应模式"""
    access_token: str
    refresh_token: str
    token_type: str = "bearer"
    expires_in: int
    user: UserProfile


class RegisterRequest(UserCreate):
    """注册请求模式"""
    confirm_password: str = Field(..., description="确认密码")

    @field_validator('confirm_password')
    @classmethod
    def passwords_match(cls, v, info):
        if 'password' in info.data and v != info.data['password']:
            raise ValueError('两次输入的密码不一致')
        return v


class RegisterResponse(BaseModel):
    """注册响应模式"""
    message: str
    user: UserResponse


class ChangePasswordRequest(BaseModel):
    """修改密码请求模式"""
    current_password: str = Field(..., description="当前密码")
    new_password: str = Field(..., min_length=8, max_length=128, description="新密码")
    confirm_password: str = Field(..., description="确认新密码")

    @field_validator('new_password')
    @classmethod
    def validate_new_password(cls, v):
        if not any(c.isupper() for c in v):
            raise ValueError('密码必须包含至少一个大写字母')
        if not any(c.islower() for c in v):
            raise ValueError('密码必须包含至少一个小写字母')
        if not any(c.isdigit() for c in v):
            raise ValueError('密码必须包含至少一个数字')
        if not any(c in '!@#$%^&*()_+-=[]{}|;:,.<>?' for c in v):
            raise ValueError('密码必须包含至少一个特殊字符')
        return v

    @field_validator('confirm_password')
    @classmethod
    def passwords_match(cls, v, info):
        if 'new_password' in info.data and v != info.data['new_password']:
            raise ValueError('两次输入的密码不一致')
        return v


class ResetPasswordRequest(BaseModel):
    """重置密码请求模式"""
    email: EmailStr = Field(..., description="邮箱地址")


class TokenRefreshRequest(BaseModel):
    """刷新令牌请求模式"""
    refresh_token: str = Field(..., description="刷新令牌")


class TokenResponse(BaseModel):
    """令牌响应模式"""
    access_token: str
    refresh_token: Optional[str] = None
    token_type: str = "bearer"
    expires_in: int


# ============ 权限检查模式 ============

class PermissionCheckRequest(BaseModel):
    """权限检查请求模式"""
    permissions: List[str] = Field(..., description="权限列表")
    require_all: bool = Field(default=False, description="是否需要所有权限")


class PermissionCheckResponse(BaseModel):
    """权限检查响应模式"""
    has_permission: bool
    missing_permissions: List[str] = []





# ============ 分页和列表模式 ============

class UserListResponse(BaseModel):
    """用户列表响应模式"""
    users: List[UserResponse]
    total: int
    page: int
    page_size: int
    total_pages: int


class RoleListResponse(BaseModel):
    """角色列表响应模式"""
    roles: List[RoleResponse]
    total: int
    page: int
    page_size: int
    total_pages: int


class PermissionListResponse(BaseModel):
    """权限列表响应模式"""
    permissions: List[PermissionResponse]
    total: int
    page: int
    page_size: int
    total_pages: int



